/**
 ** term - A terminal interface
 *
 * The term module provides a command-line interface for interacting with the
 * system.
 *
 */

define('oj/term',
[
'oj/os',
'oj/element'
],
function (os, element) {
    'use strict';
    
    var term = {
        
        /* Objects */
        Term : function () {}
        
    };
    
    
    
    term.Term = function() {
        /**
         ** Term - Term object
         *
         */
        
        var self = this;
        
        
        var COMMANDS = {
             
            'cd': {
                'help': "cd 'path'      - Change the current working directory",
                'do': function (args) {
                    self.print_style = 'term_files';
                    os.chdir(args[ 1 ], self.response);
                    self.setprompt( '' );
                }
            },
            
            'cp': {
                'help': "cp 'src' 'dst' - Copy a file",
                'do': function (args) {
                    args.shift();
                    args[ 0 ] = os.path.abspath( args[ 0 ] );
                    args[ 1 ] = os.path.abspath( args[ 1 ] );
                    os.concat( args, false, self.response );
                    self.setprompt( '' );
                }
            },
            
            'help': {
                'help': "help           - List available commands",
                'do': function (args) {
                    Object.keys(COMMANDS).forEach(function (cmd) {
                        self.print(COMMANDS[cmd]['help']);
                    });
                    self.response();
                }
            },
            
            'id': {
                'help': "id             - Get user identity",
                'do': function (args) {
                    self.print(os.environ.user.name);
                    self.response();
                }
            },
            
            'logout': {
                'help': "logout         - Log current user out",
                'do': function (args) {
                    os.logout(document.location, function(m) {
                        document.location = m.logout;
                    });
                }
            },
            
            'ls': {
                'help': "ls ['path']    - List files",
                'do': function (args) {
                    var dir = '-';
                    
                    args.shift();
                    
                    while (dir.charAt(0) === '-' && args.length > 0) {
                        dir = args.shift();
                    }
                    
                    if (dir.charAt(0) === '-') {
                        dir = '.';
                    }
                    
                    self.print_style = 'term_files';
                    os.listdir(dir, self.response);
                    self.setprompt( '' );
                }
            },
            
            'mkdir': {
                'help': "mkdir 'path'   - Make a directory",
                'do': function (args) {
                    os.mkdir( args[ 1 ], self.response );
                    self.setprompt('');
                }
            },
            
            'mv': {
                'help': "mv 'src' 'dst' - Move file or directory",
                'do': function (args) {
                    os.move(args[1], args[2], self.response);
                    self.setprompt('');
                }
            },
            
            'print': {
                'help': "print          - Send the screen to the printer",
                'do': function (args) {
                    window.print();
                    self.response();
                }
            },
            
            'rm': {
                'help': "rm 'path'      - Remove file",
                'do': function (args) {
                    os.remove(args[1], self.response);
                    self.setprompt('');
                }
            },
            
            'rmdir': {
                'help': "rmdir 'path'   - Remove directory",
                'do': function (args) {
                    os.rmdir(args[1], self.response);
                    self.setprompt('');
                }
            },
            
            'time': {
                'help': "time           - Get current local time",
                'do': function (args) {
                    self.print((new Date()).toLocaleString());
                    self.response();
                }
            },
            
            'version': {
                'help': "version        - Get oj version",
                'do': function (args) {
                    self.print('oj ' + oj.version);
                    self.response();
                }
            }
        };
        
        
        self.init = function (container) {
            /**
             *>init(container)
             *
             * Initialises the Term instance.
             *
             */
            
            self.container = container;
            
            self.container.style['background'] = '-webkit-radial-gradient(center center, farthest-corner, rgba( 0, 100, 0, 1 ), black) center center fixed, black';
            self.container.style['background'] = '-moz-radial-gradient(center center, farthest-corner, rgba( 0, 100, 0, 1 ), black) center center fixed, black';
            
            self.buffer = [];
            self.callback = undefined;
            self.panel = element.create(self.container, 'div', 'term_container');
            self.history = element.create(self.panel, 'div', 'term_history');
            self.prm = element.create(self.panel, 'span', 'term_prompt');
            
            self.print_style = '';
            self.prm.style.paddingRight = '2px';
            
            self.cmd = element.create(self.panel, 'input', 'term_cmdline', {'type': 'text'});
            self.cmd.onfocus = function() {self.cmd.style.outline='none'};
            
            self.panel.onresize = self.layout;
            self.panel.onclick = self.focus;
            
            document.onclick = self.focus;
            
            // pressing enter in cmd will write submit to the input
            self.cmd.onkeypress = function(event) {
                if (event.keyCode != '13') return true;
                
                var p = self.prm.cloneNode(true),
                    input = self.cmd.value;
            
                p.style.marginRight = '1px';
                self.cmd.value = '';
            
                self.print(element.create('span', '', [ p,
                    element.create('span', 'term_cmdline', [input])
                ]));
                
                if (input.length > 0 && self.callback) {
                    var fn = self.callback;
                    self.callback = undefined;
                    fn(input);
                }
            }
            
            os.environ.term_history = 100;
            
            
            return self;
        };
        
        
        self.print = function (output) {
            /**
             *>print(output)
             *
             * Writes output to the history buffer.
             *
             */
            
            if (self.buffer.length === os.environ.term_history) {
                self.history.removeChild(self.buffer.shift());
            }
            
            if (!(output instanceof HTMLElement)) {
                if (typeof output === 'undefined') {
                    output = '';
                } else if (typeof output === 'object') {
                    if (output.hasOwnProperty('error')) {
                        self.print_style = 'term_error';
                    }
                    output = JSON.stringify(output);
                }
                output = output.replace(/", "|","|"]|"}/g, '\n');
                output = output.replace(/\["|{"|\[\]/g, '');
                output = output.replace(/":"|": "/g, ': ');
                output = output.replace(/\\\//g, '/');
            }
            
            self.buffer.push(element.create(self.history, 'div', 'term_print ' + self.print_style, [output]));
            self.cmd.scrollIntoView();
            
            return self;
        };
        
        
        self.read = function (prompt, fn) {
            /**
             *>read('prompt', callback)
             *
             * Read input from the user.
             *
             */
            
            self.setprompt(prompt);
            self.cmd.focus();
            self.callback = fn;
            
            return self;
        };
        
        
        self.setprompt = function (prompt) {
            /**
             *>setprompt('prompt')
             *
             * Updates the prompt component value.
             *
             */
            
            for (var prop in os.environ) {
                prompt = prompt.replace('$'+prop, os.environ[prop]);
            }
            
            self.prm.textContent = prompt;
            os.environ.prompt = prompt;
            self.layout();
            
            return self;
        };
        
        
        self.response = function (response) {
            /**
             *>response(response)
             *
             * Prints the response and prompts for input.
             *
             */
            self.print(response);
            self.read('$cwd#', self.execute);
        };
        
        
        self.execute = function (input) {
            /**
             *>execute('input')
             *
             * Executes a pipe separated string of commands.
             *
             */
            
            var cmd = input.split(' ');
            
            self.print_style = '';
            
            if (cmd[0] in COMMANDS) {
                COMMANDS[cmd[0]]['do'](cmd);
            } else {
                var prog = '?' + cmd[0];
                
                if (cmd.length > 1) {
                    prog += '&f=' + os.path.abspath(cmd[1]);
                }
                
                window.open(prog, cmd[0] + '-' + cmd[1]);
                self.response();
            }
            
            return self;
        };
        
        
        self.layout = function () {
            /**
             *>layout()
             *
             * Updates the layout of the display.
             *
             */
            
            self.cmd.style.width = (self.panel.offsetWidth - self.prm.offsetWidth - 30) + 'px';
            
            return self;
        };
        
    }
    
    
    if (oj.main === 'oj/term') {
        /**
         **oj.main
         *
         * When run as the main application this module will automatically
         * create a Term instance using document.body as the container.
         *
         * Available commands
         *
         *./# help
         *.cd 'path'      - Change the current working directory
         *.cp 'src' 'dst' - Copy a file
         *.help           - List available commands
         *.id             - Get user identity
         *.logout         - Log current user out
         *.ls ['path']    - List files
         *.mkdir 'path'   - Make a directory
         *.mv 'src' 'dst' - Move file or directory
         *.print          - Send the screen to the printer
         *.rm 'path'      - Remove file
         *.rmdir 'path'   - Remove directory
         *.time           - Get current local time
         *.version        - Get oj version 
         *
         */
        
        os.identity(document.location, function(m) {
            if (m.hasOwnProperty('login')) {
                document.location = m.login;
                return;
            }
            
            os.environ.user = m;
            
            var sh = (new term.Term).init(document.body);
            
            sh.print('Welcome ' + os.environ.user.name);
            sh.print((new Date()).toLocaleString());
            sh.print('oj ' + oj.version);
            sh.print();
            sh.print("Type 'help' for a list of commands.");
            sh.print();
            sh.read('$cwd#', sh.execute);
        } );
        
        element.create(document.head, 'syle', {'type': 'text/css'}, [
            'html {',
            '  height: 100%;',
            '}',
            'body {',
            '  height: 100%;',
            '}'
        ]);
    }
    
    
    element.create(document.head, 'style', {'type': 'text/css'}, [
        '.term_container {',
        '  color: #cccccc;',
        '  border: 0;',
        '  margin: 0;',
        '  padding: 5px;',
        '  font: normal normal normal 16pt monospace;',
        '  white-space: pre;',
        '}',
        '.term_history {',
        '}',
        '.term_prompt {',
        '  color: white;',
        '}',
        '.term_cmdline {',
        '  color: #cccccc;',
        '  background: none;',
        '  font: normal normal normal 16pt monospace;',
        '  white-space: pre;',
        '  border: 0;',
        '}',
        '.term_print {',
        '  padding-top: 3px;',
        '}',
        '.term_files {',
        '  color: #00ff00;',
        '}',
        '.term_error {',
        '  color: #ff0000;',
        '}'
    ]);
    
    
    return term;
    
});
